﻿// -----------------------------------------------------------------------
// <copyright file="IStream.cs" company="Company">
// Company 2011
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Runtime;
using System.Runtime.InteropServices;

namespace Company.IO.Interfaces
{
    /// <summary>
    /// Provides a generic view of a sequence of bytes.
    /// </summary>
    [Guid("b1bc78a7-c14f-45cf-ae4e-8295bc1ff54a")]
    public interface IStream : IDisposable
    {
        /// <summary>
        /// When overridden in a derived class, this property gets a value that indicates whether the current Stream object supports reading. 
        /// </summary>
        bool CanRead { get; }

        /// <summary>
        /// When overridden in a derived class, this property gets a value that indicates whether the current Stream object supports seeking. 
        /// </summary>
        bool CanSeek { get; }

        /// <summary>
        /// When overridden in a derived class, this property gets a value that indicates whether the current Stream object can have a time-out. 
        /// </summary>
        [ComVisible(false)]
        bool CanTimeout { get; }

        /// <summary>
        /// When overridden in a derived class, this property gets a value that indicates whether the current Stream object supports writing. 
        /// </summary>
        bool CanWrite { get; }

        /// <summary>
        /// When overridden in a derived class, this property gets the length of the current Stream object, in bytes. 
        /// </summary>
        long Length { get; }

        /// <summary>
        /// When overridden in a derived class, this property gets or sets the current position within the current Stream object. 
        /// </summary>
        long Position { get; set; }

        /// <summary>
        /// Gets or sets the amount of time a read operation blocks waiting for data. 
        /// </summary>
        [ComVisible(false)]
        int ReadTimeout { get; set; }

        /// <summary>
        /// Gets or sets the amount of time a write operation blocks waiting for data. 
        /// </summary>
        [ComVisible(false)]
        int WriteTimeout { get; set; }

        /// <summary>
        /// Closes the current Stream object and releases any resources (such as sockets and file handles) associated with it. 
        /// </summary>
        void Close();

        /// <summary>
        /// When overridden in a derived class, this method clears all buffers for the 
        /// current Stream object and causes any buffered data to be written to the underlying device. 
        /// </summary>
        void Flush();

        /// <summary>
        /// <para>
        /// When overridden in a derived class, this method sets the position within the current Stream object. 
        /// </para>
        /// </summary>
        /// <param name="offset">
        /// <para>
        /// A byte offset relative to the origin parameter. A positive value seeks forward from the origin parameter. 
        /// A negative value seeks backward. 
        /// </para>
        /// </param>
        /// <param name="origin">
        /// <para>
        /// A SeekOrigin value that indicates the reference point to be used to obtain the new position.
        /// </para>
        /// </param>
        /// <returns>The new position within the current stream.</returns>
        long Seek(long offset, SeekOrigin origin);

        /// <summary>
        /// <para>
        /// When overridden in a derived class, this method sets the length of the current Stream object. 
        /// </para>
        /// </summary>
        /// <param name="value">
        /// <para>
        /// The length you want for the current stream, in bytes.
        /// </para>
        /// </param>
        void SetLength(long value);

        /// <summary>
        /// When overridden in a derived class, this method reads a sequence of bytes from the 
        /// current Stream object and advances the position within the stream by the number of bytes tbat are read.
        /// </summary>
        /// <param name="buffer">
        /// <para>
        /// An array of bytes. When this method returns a value, 
        /// the buffer contains the specified byte array that includes the values from the 
        /// offset parameter through (offset + count - 1) replaced by the bytes read from the current source.
        /// </para>
        /// </param>
        /// <param name="offset">
        /// <para>
        /// The 0-based byte offset in the buffer parameter at which you want to begin storing the data that is read from the current stream.
        /// </para>
        /// </param>
        /// <param name="count">
        /// <para>
        /// The maximum number of bytes to be read from the current stream.
        /// </para>
        /// </param>
        /// <returns>
        /// <para>
        /// The total number of bytes that are read into the buffer. 
        /// This can be less than the number of bytes requested, if that many bytes are not currently available. 
        /// Note that the return value is 0 (zero) if the end of the stream has been reached.
        /// </para>
        /// </returns>
        int Read([In, Out] byte[] buffer, int offset, int count);

        /// <summary>
        /// Reads a byte from the current Stream object and advances the position 
        /// within the stream by one byte, or returns -1 if the end of the stream has been reached.
        /// </summary>
        /// <returns>
        /// <para>
        /// The unsigned byte cast to an Int32 variable, or -1 if the end of the stream has been reached.
        /// </para>
        /// </returns>
        [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
        int ReadByte();

        /// <summary>
        /// <para>
        /// When overridden in a derived class, this method writes a sequence of bytes to the current Stream 
        /// object and advances the current position within this stream by the number of bytes written to it. 
        /// </para>
        /// </summary>
        /// <param name="buffer">
        /// <para>
        /// An array of bytes from which the number of bytes specified in the buffer parameter are written to the current stream. 
        /// </para>
        /// </param>
        /// <param name="offset">
        /// <para>
        /// The 0-based byte offset in the buffer at which copying bytes to the current stream is to begin.
        /// </para>
        /// </param>
        /// <param name="count">
        /// <para>
        /// The number of bytes to be written to the current stream.
        /// </para>
        /// </param>
        void Write(byte[] buffer, int offset, int count);

        /// <summary>
        /// <para>
        /// Writes a specified byte to the current position in the current Stream object 
        /// and advances the position within the stream by one byte.
        /// </para>
        /// </summary>
        /// <param name="value">
        /// <para>
        /// The byte to be written to the current stream.
        /// </para>
        /// </param>
        void WriteByte(byte value);
    }
}